package geektime.spring.springbucks;

import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.filter.FilterEventAdapter;
import com.alibaba.druid.proxy.jdbc.*;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.stat.JdbcConnectionStat;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionException;

import java.util.List;
import java.util.Properties;

@Slf4j
public class ConnectionLogFilter extends FilterEventAdapter {

    @Override
    public void connection_connectBefore(FilterChain chain, Properties info) {
        log.info("BEFORE CONNECTION!");
    }

    @Override
    public void connection_connectAfter(ConnectionProxy connection) {
        log.info("AFTER CONNECTION!");
    }

    @Override
    protected void statementExecuteQueryBefore(StatementProxy statement, String sql) {
        List<SQLStatement> stmtlist=SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
        for (SQLStatement s:stmtlist  ) {
            MySqlSchemaStatVisitor visitor=new MySqlSchemaStatVisitor();
            s.accept(visitor);
        }
    }

    @Override
    protected void statementExecuteBefore(StatementProxy statement, String sql) {
        List<SQLStatement> stmtlist=SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
        for (SQLStatement s:stmtlist  ) {
            MySqlSchemaStatVisitor visitor=new MySqlSchemaStatVisitor();
            s.accept(visitor);

            List<TableStat.Condition> l=visitor.getConditions();
            for(int i=0;i<l.size();i++){
                TableStat.Condition c=l.get(i);
                if(c.getValues().size()>9){
                    System.err.println(c.getColumn()+" in 内容不得超过10条数据");
                    throw new SqlSessionException();
                }
            }

        }
    }




   /*private SQLUtils.FormatOption statementSqlFormatOption = new SQLUtils.FormatOption(false, true);

    protected void statementLog(String message) {
        try {
            String sql = message;
            System.out.println(sql);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {
        logExecutableSql(statement, sql);
    }

    @Override
    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) {
        logExecutableSql(statement, sql);
    }

    @Override
    protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {
        logExecutableSql(statement, sql);
    }

    @Override
    protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {
        if (statement instanceof PreparedStatementProxy) {
            String sql = ((PreparedStatementProxy) statement).getSql();
            logBatchExecutableSql(statement, sql);
        }
        List<String> sqls = statement.getBatchSqlList();
        if (sqls != null) {
            for (String sql : sqls) {
                logExecutableSql(statement, sql);
            }
        }
    }

    private static final String BATCH_PSTMT_ARGS = "batch-pstmt-args";

    @Override
    public void preparedStatement_addBatch(FilterChain chain, PreparedStatementProxy statement) throws SQLException {
        List<Object> parameters = formatParameters(statement);
        List<List<Object>> args = (List<List<Object>>) statement.getAttribute(BATCH_PSTMT_ARGS);
        if (args == null) {
            args = new ArrayList<>();
            statement.putAttribute(BATCH_PSTMT_ARGS, args);
        }
        args.add(parameters);
        super.preparedStatement_addBatch(chain, statement);
    }

    private void logBatchExecutableSql(StatementProxy statement, String sql) {
        List<List<Object>> args = (List<List<Object>>) statement.getAttribute(BATCH_PSTMT_ARGS);
        if (args != null && args.size() > 0) {
            for (List<Object> parameters : args) {
                String formattedSql = formattedSql(statement, sql, parameters);
                statementLog(formattedSql);
            }
            args.clear();
        }
    }

    private void logExecutableSql(StatementProxy statement, String sql) {
        int parametersSize = statement.getParametersSize();
        if (parametersSize == 0) {
            statementLog(sql);
            return;
        }
        List<Object> parameters = formatParameters(statement);
        String formattedSql = formattedSql(statement, sql, parameters);
        statementLog(formattedSql);
    }

    private String formattedSql(StatementProxy statement, String sql, List<Object> parameters) {
        String dbType = statement.getConnectionProxy().getDirectDataSource().getDbType();
        String formattedSql = SQLUtils.format(sql, dbType, parameters, this.statementSqlFormatOption);
        return formattedSql;
    }

    private List<Object> formatParameters(StatementProxy statement) {
        int parametersSize = statement.getParametersSize();
        List<Object> parameters = new ArrayList<Object>(parametersSize);
        for (int i = 0; i < parametersSize; ++i) {
            JdbcParameter jdbcParam = statement.getParameter(i);
            parameters.add(jdbcParam != null ? jdbcParam.getValue() : null);
        }
        return parameters;
    }
 */


}
